package com.ljf.framework.util.tree;

import com.ljf.framework.exception.LjfException;
import com.ljf.framework.util.ObjectUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

/**
 * @Auther: lijinfeng
 * @Date: 2022/4/22
 * @Description 描述: 构建tree对象的工具
 * <p>
 * 只要对象拥有以下三个属性，配合TreeObject类 即可使用该工具构件tree对象
 * Long id;
 * Long parentId;
 * String name;
 */

public class TreeUtil {

    private TreeUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * @description: 检查对象属性是否符合要求
     * @author: lijinfeng
     * @date: 2022/5/12
     * @param: [t]
     * @return: boolean
     */
    public static <T> boolean check(T t) {
        Field fieldId;
        Field fieldParentId;
        Field fieldName;

        // 检查必须属性
        try {
            fieldId = t.getClass().getDeclaredField("id");
        } catch (NoSuchFieldException e) {
            throw new LjfException(t.getClass() + ":该对象没有id属性");
        }
        try {
            fieldParentId = t.getClass().getDeclaredField("parentId");
        } catch (NoSuchFieldException e) {
            throw new LjfException(t.getClass() + ":该对象没有parentId属性");
        }
        try {
            fieldName = t.getClass().getDeclaredField("name");
        } catch (NoSuchFieldException e) {
            throw new LjfException(t.getClass() + ":该对象没有name属性");
        }

        // 获取属性值
        try {
            fieldId.setAccessible(true);
            Long.valueOf(fieldId.get(t).toString());
        } catch (IllegalAccessException e) {
            throw new LjfException(t.getClass() + ":获取Id属性值失败");
        }
        try {
            fieldParentId.setAccessible(true);
            Long.valueOf(fieldParentId.get(t).toString());
        } catch (IllegalAccessException e) {
            throw new LjfException(t.getClass() + ":获取parentId属性值失败");
        }
        try {
            fieldName.setAccessible(true);
            fieldName.get(t).toString();
        } catch (IllegalAccessException e) {
            throw new LjfException(t.getClass() + ":获取name属性值失败");
        }
        return true;
    }


    /**
     * 将java对象转成TreeObject集合 （其实是一个map集合）
     *
     * @param bean
     * @return
     * @throws Exception
     */
    public static TreeObject beanConvertMap(Object bean) {

        TreeObject dataMap = new TreeObject();
        // 获取bean的字节码对象
        Class clazz = bean.getClass();
        // 获取对象的所有属性
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            // 获取对象的属性
            Field field = fields[i];
            // 打开私有访问
            field.setAccessible(true);
            // 获取对象的属性名称
            String name = field.getName();
            // 获取对象的属性值
            Object value = null;
            try {
                value = field.get(bean);
            } catch (IllegalAccessException e) {
                throw new LjfException("获取" + name + "的值失败。");
            }
            // 将对象的属性和属性值封装到map集合中
            switch (name) {
                case TreeObject.ID:
                    dataMap.put(TreeObject.ID, value);
                    break;
                case TreeObject.PARENT_ID:
                    dataMap.put(TreeObject.PARENT_ID, value);
                    break;
                case TreeObject.NAME:
                    dataMap.put(TreeObject.NAME, value);
                    break;
                case TreeObject.CHILDREN:
                    dataMap.put(TreeObject.CHILDREN, value);
                    break;
            }
            // 将原属性装成一个map对象
            Object data = dataMap.get(TreeObject.DATA);
            if(ObjectUtil.isEmpty(data)){
                HashMap<Object, Object> hashMap = new HashMap<>();
                hashMap.put(name, value);
                dataMap.put(TreeObject.DATA, hashMap);
            }else {
                HashMap<Object, Object> hashMap = (HashMap<Object, Object>) data;
                hashMap.put(name, value);
                dataMap.put(TreeObject.DATA, hashMap);
            }
        }
        return dataMap;
    }


    /**
     * 将普通对象转化为树对象
     *
     * @param t
     * @return
     */
    public static <T> TreeObject getTreeObject(T t) {
        // 检查属性符合TreeObject标准
        check(t);
        // 原属性放到map中
        return beanConvertMap(t);
    }

    /**
     * 将普通对象转化为树对象
     *
     * @param list
     * @return
     */
    public static <T> List<TreeObject> getTreeObjectList(List<T> list) {
        List<TreeObject> treeObjectList = new ArrayList<>();
        if (null != list && !list.isEmpty()) {
            for (T t : list) {
                TreeObject treeObject = getTreeObject(t);
                treeObjectList.add(treeObject);
            }
        }
        return treeObjectList;
    }

    /**
     * @description: 使用递归获取根节点下面得孩子
     * @author: lijinfeng
     * @date: 2022/5/10
     * @param: [id, allTree]
     * @return: java.util.List<com.ljf.system.utile.TreeObject>
     */
    public static List<TreeObject> getChildren(Long id, List<TreeObject> allTree) {
        List<TreeObject> childrenList = new ArrayList<>();
        allTree.forEach(tree -> {
            if (tree.get(TreeObject.PARENT_ID).equals(id)) {
                childrenList.add(tree);
            }
        });

        if (!childrenList.isEmpty()) {
            childrenList.forEach(tree -> {
                List<TreeObject> children = getChildren((Long) tree.get(TreeObject.ID), allTree);
                // 如果没有下级菜单，则不添加CHILDREN属性，前端可认为该层级为末级
                if (!children.isEmpty()) {
                    tree.put(TreeObject.CHILDREN, children);
                }
            });

        } else {
            return Collections.emptyList();
        }
        return childrenList;
    }

    /**
     * @description: 获取树结构list
     * @author: lijinfeng
     * @date: 2022/5/10
     * @param: [list]
     * @return: java.util.List<com.ljf.system.utile.TreeObject>
     */
    public static <T> List<TreeObject> getTree(List<T> list) {

        List<TreeObject> treeObjectList = getTreeObjectList(list);

        List<TreeObject> treeList = new ArrayList<>();
        treeObjectList.forEach(item -> {
            if ((Long) item.get(TreeObject.PARENT_ID) == 0) {
                treeList.add(item);
            }
        });

        if (!treeList.isEmpty()) {
            treeList.forEach(item -> {
                //使用递归获取孩子
                List<TreeObject> childrenList = getChildren((Long) item.get(TreeObject.ID), treeObjectList);
                // 如果没有下级菜单，则不添加CHILDREN属性，前端可认为该层级为末级
                if (!childrenList.isEmpty())
                    item.put(TreeObject.CHILDREN, childrenList);
            });
        }

        return treeList;
    }

    /**
     * @description: 尝试优化
     * @author: lijinfeng
     * @date: 2022/5/10
     * @param: [list]
     * @return: java.util.List<com.ljf.system.utile.TreeObject>
     */
    public static <T> List<TreeObject> getTreeV1(List<T> list) {
        List<TreeObject> treeList = new ArrayList<>();
        List<TreeObject> treeObjectList = getTreeObjectList(list);

        treeObjectList.forEach(item -> {
            TreeObject treeObject = getTreeObject(item);
            if ((Long) treeObject.get(TreeObject.PARENT_ID) == 0) {
                treeList.add(treeObject);
            }
            // 将剩余的放到map中

        });

        if (!treeList.isEmpty()) {
            treeList.forEach(item -> {

            });
        }

        return treeList;
    }

}
